module Vina

using Printf
using Utils
import Base.string

mutable struct Config
    receptor::String
    ligand::String
    spacing::Float64
    size::Array{Float64}
    center::Array{Float64}
    output::String
    log::String
    cpu_num::Int32
    seed::Int32
    exhaustiveness::Int32
    num_modes::Int32
    energy_range::Float64
end

export Config, read_config, gen_vina_config

function read_config(infilename::String)
    config = readlines(infilename)
    receptor = strip(config[1])
    ligand = "ligand"
    spacing = parse(Float64, split(config[2])[2])
    size = (s -> parse(Float64, s) * spacing).(split(config[3])[2:end])
    center = (c -> parse(Float64, c)).(split(config[4])[2:end])
    output = "ligand_out"
    log = "log"
    cpu_num = 0
    seed = 0
    exhaustiveness = 8
    num_modes = 9
    energy_range = 3
    finish_hint("Finished reading config file.\n")
    return Config(receptor, ligand, spacing, size, center, output, log, cpu_num, seed, exhaustiveness, num_modes, energy_range)
end

function string(config::Config)
    s = "receptor = " * config.receptor * ".pdbqt\n" * "ligand = " * config.ligand * ".pdbqt\n" * "\n" *
        "size_x = " * @sprintf("%.2f", config.size[1]) * "\n" *
        "size_y = " * @sprintf("%.2f", config.size[2]) * "\n" *
        "size_z = " * @sprintf("%.2f", config.size[3]) * "\n" *
        "center_x = " * @sprintf("%.2f", config.center[1]) * "\n" *
        "center_y = " * @sprintf("%.2f", config.center[2]) * "\n" *
        "center_z = " * @sprintf("%.2f", config.center[3]) * "\n" *
        "\n" * "out = " * config.output * ".pdbqt\n" * "log = " * config.log * ".txt\n" * "\n"
    if config.cpu_num != 0
        s *= "cpu = " * "$(config.cpu_num)" * "\n"
    end
    if config.seed != 0
        s *= "seed = " * "$(config.seed)" * "\n"
    end
    if config.exhaustiveness != 8
        s *= "exhaustiveness = " * "$(config.exhaustiveness)" * "\n"
    end
    if config.num_modes != 9
        s *= "num_modes = " * "$(config.num_modes)" * "\n"
    end
    if config.energy_range != 3
        s *= "energy_range = " * "$(config.energy_range)"
    end
    return s
end

function gen_vina_config(config::Config, new_config_file::AbstractString)
    new_config = open(new_config_file, "w")
    write(new_config, string(config))
    close(new_config)
end

function print_config(config::Config)
    finish_hint("\nCurrent Autodock Vina configuration file:\n")
    println(string(config))
end

end